package com.shuqi.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.text.TextUtils;

import com.shuqi.common.MyTask;
import com.shuqi.database.dao.impl.TxtCatalogDao;
import com.shuqi.model.bean.BookContentInfo;

public class CheckTxtCatalogTool {
    private String Tag = "TxtTool";

    private static Context context;
    /** 单例对象 */
    private static CheckTxtCatalogTool catalogTool = null;
    /** 回调监听器 */
    private OnCheckingListener checkingListener = null;

    /** 是否正在检查 */
    private boolean isChecking = false;
    /** 是否需要停止检查 */
    private boolean isStop = false;

    private String filePath;

    /** 断章时，缓存中的目录数据 */
    private List<BookContentInfo> mRunCatalogList = null;

    /** 停止检查并重置数据 */
    public void stopCheck() {
        isStop = true;
    }

    /**
     * 得到智能断章的实例对象
     * 
     * @param context
     * @return
     */
    public static CheckTxtCatalogTool getInstance() {
        if (catalogTool == null) {
            catalogTool = new CheckTxtCatalogTool();
        }
        return catalogTool;
    }

    public static void onDestoryCheckTxtCatalogToolInstance() {
        catalogTool = null;
        Log4an.e("BookContentLocalAppTXTParser",
                "**********onDestoryCheckTxtCatalogToolInstance**********");
    }

    public List<BookContentInfo> getmRunCatalogList() {
        return mRunCatalogList;
    }

    public void setmRunCatalogList(List<BookContentInfo> mRunCatalogList) {
        this.mRunCatalogList = mRunCatalogList;
    }



    public interface OnCheckingListener {
        public void onUpdate(List<BookContentInfo> templist, int percent, String checkedName);

        /**
         * 
         * @param finalList
         * @param isRealFinish 7.3.8 所有目录是否全部断章完成标记
         */
        public void onFinish(List<BookContentInfo> finalList, boolean isRealFinish);
    }

    /**
     * 检查文件是否正在检查目录
     * 
     * @param filePath
     * @return
     */
    public boolean isChecking(String filePath) {
        if (TextUtils.isEmpty(filePath)) {
            return false;
        }
        return filePath.equals(this.filePath) && isChecking;
    }

    /**
     * 获取正在智能断章的文件
     * 
     * @return
     */
    public String getCheckingFilePath() {
        return filePath;
    }

    /**
     * 进行智能断章
     * 
     * @param filePath 文件路径
     * @param oldList 需要增量更新智能断章时，传递原有的章节数据。此方法根据最后一条的索引开始检查。正常断章传递 null
     * @param context
     * @param checkingListener 不需要传递null
     */
    public void check(final String filePath, final Context context,
            OnCheckingListener checkingListener) {
        Log4an.e(Tag, "开启智能断章：path：" + filePath);
        this.checkingListener = checkingListener;
        CheckTxtCatalogTool.context = context;
        if (TextUtils.isEmpty(filePath) || (filePath.equals(this.filePath) && isChecking)) {
            Log4an.e(Tag, "开启检查失败：该文件正在智能断章:" + filePath);
            return;
        } else {
            stopCheck();
        }
        MyTask.runInBackground(new Runnable() {
            @Override
            public void run() {
                startCheck(filePath);
            }
        }, true);

    }

    // /**
    // * 进行智能断章，同步操作。不会单独开辟一个线程，不能运行在ui线程中
    // *
    // * @param filePath 文件路径
    // * @param oldList 需要增量更新智能断章时，传递原有的章节数据。此方法根据最后一条的索引开始检查。正常断章传递 null
    // * @param context
    // * @param checkingListener 不需要传递null
    // */
    // public void checkSyn1(final String filePath, final Context context,
    // OnCheckingListener checkingListener) {
    // Log4an.e(Tag, "开启智能断章：path：" + filePath);
    // this.checkingListener = checkingListener;
    // CheckTxtCatalogTool.context = context;
    // if (TextUtils.isEmpty(filePath) || (filePath.equals(this.filePath) && isChecking)) {
    // Log4an.e(Tag, "开启检查失败：该文件正在智能断章:" + filePath);
    // return;
    // } else {
    // stopCheck();
    // }
    // startCheck(filePath);
    //
    // }

    /**
     * 开始智能断章
     * 
     * @param filePath 文件path
     * @param oldList 增量更新的老目录数据，正常断章传递：null
     */
    private synchronized void startCheck(String filePath) {
        Log4an.e(Tag, "startCheck: 1.filePath = " + filePath);
        File file = new File(filePath);
        if (!file.exists() || isChecking) {
            Log4an.e(Tag, "startCheck: 2.exists:" + file.exists() + ",isChecking:" + isChecking);
            return;
        }
        this.filePath = filePath;
        // String checkedTitle = "";
        Log4an.e(Tag, "文件大小：" + file.length());
        int percent = 0;
        try {
            isChecking = true;
            isStop = false;
            long fileSize = file.length();
            // 获得文件编码类型，如果是”windows-1252“,则文件的正确编码格式为"Unicode" 其他格式则尝试用GBK解析
            long st = System.currentTimeMillis();
            String type = Util.getTxtFileEncoding(context, filePath);
            Log4an.e(Tag, "获取编码所需时间：" + (System.currentTimeMillis() - st));
            Log4an.e(Tag, "3.txt 开始智能断章  encoding: " + type);

            // 第*章的集合
            List<BookContentInfo> temp = new ArrayList<BookContentInfo>();
            // ---的集合
            List<BookContentInfo> temp1 = new ArrayList<BookContentInfo>();
            // \n的集合
            List<BookContentInfo> temp2 = new ArrayList<BookContentInfo>();
            BookContentInfo info = null;
            String reg = "^\\s*([0-9]+\\|)|([【第]\\s*[０-９0-9零一二三四五六七八九十百千万]+\\s*[】书首集卷回章节部]+)";
            String someString = "----------";

            Pattern pattern = Pattern.compile(reg);
            FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, type);
            CustomBufferReader br = new CustomBufferReader(isr);
            int num = 0;
            int length = 0;
            String s;
            String lastString = null;
            String t1 = " ";
            String t2 = "　";
            String t3 = "第";
            String t4 = "";
            String t5 = "【";
            String t6 = "|";
            int enterNum = 0;

            if (checkingListener == null) {
                Log4an.e(Tag, "4.开始读流:无回调监听器");
            }
            int byteLen = 0;// 字节长度
            int byteIndex = 0;
            // 为了区分\n, \r, \r\n等几种方式的换行，skip需要动态获取
            int skips[] = new int[1];
            int skip = 0;// 根据编码不同，段落结尾处理不同
            long start = System.currentTimeMillis();
            while ((s = br.readLine(skips)) != null) {
                skip = skips[0];
                if (isStop) {
                    return;
                }
                
                byteLen = (s.getBytes(type).length + skip);
                length = s.length() + skip;
                Matcher matcher = pattern.matcher(s);
                if (s.length() < 40 && matcher.find()) {

                    int index;
                    if (s.indexOf(t6) >= 0) {
                        index = s.indexOf(t6) + 1;
                    } else if (s.indexOf(t5) >= 0) {
                        index = s.indexOf(t5);
                    } else {
                        index = s.indexOf(t3);
                    }
                    if (index >= 0) {
                        s = s.substring(index);
                    }
                    while (!TextUtils.isEmpty(s) && (s.startsWith(t1) || s.startsWith(t2))) {
                        s = s.substring(1);
                    }
                    // Log4an.d("1", "【1】s：" + s + " ;byteIndex： " + byteIndex);
                    try {
                        if (temp.size() > 0) {
                            String s1 = s.replaceAll(t1, "").replaceAll(t2, "");
                            String s2 =
                                    temp.get(temp.size() - 1).getCurChapterName()
                                            .replaceAll(t1, "").replaceAll(t2, "");
                            if (temp.size() > 0 && (s1.equals(s2) || s2.endsWith(s1))) {
                                num += length;
                                continue;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    info = new BookContentInfo();
                    info.setCurChapterName(s);
                    info.setStartIndex(byteIndex);
                    if (temp.size() > 0) {
                        temp.get(temp.size() - 1).setEndIndex(byteIndex);
                        // Log4an.i("1", "【1】end=" + temp.get(temp.size() - 1).getEndIndex());
                    }
                    temp.add(info);
                    // Log4an.d("1", "【1】s：" + s + " ;byteIndex： " + byteIndex);
                    // byteIndex+=byteLen;
                } else if (s.length() < 40 && s.contains(someString)) {
                    info = new BookContentInfo();
                    info.setCurChapterName(lastString == null ? "" : lastString);
                    info.setStartIndex(byteIndex);
                    if (temp.size() > 0) {
                        temp.get(temp.size() - 1).setEndIndex(byteIndex);
                        // Log4an.i("1", "【2】end=" + temp.get(temp.size() - 1).getEndIndex());
                    }
                    // Log4an.d("1", "【2】s：" + s + " ;byteIndex： " + byteIndex);
                    temp1.add(info);
                } else if (enterNum >= 4) {
                    String s_ = s.replaceAll(t1, "").replaceAll(t2, "");
                    if (!t4.equals(s_)) {
                        info = new BookContentInfo();
                        info.setCurChapterName(s_);
                        info.setStartIndex(byteIndex);
                        if (temp.size() > 0) {
                            temp.get(temp.size() - 1).setEndIndex(byteIndex);
                            // Log4an.i("1", "【3】end=" + temp.get(temp.size() - 1).getEndIndex());
                        }
                        // Log4an.d("1", "【3】s：" + s + " ;byteIndex： " + byteIndex);
                        temp2.add(info);
                    }
                }
                // 记录上一个字符串
                lastString = s;
                byteIndex += byteLen;

                // Log4an.d("1", "byteIndex=" + byteIndex + ";byteLen=" + byteLen);
                num += length;
                int p = (int) (num * 100 / (fileSize / 2));
                if (percent != p) {
                    percent = p;
                    if (percent > 100) {
                        percent = 100;
                    }

                    if (checkingListener != null) {
                        if (temp != null && temp.size() >= 1) {
                            checkingListener.onFinish(temp, false);
                            catalogTool.setmRunCatalogList(temp);
                        }
                        checkingListener.onUpdate(temp, percent, null);// checkedTitle
                    }
                }
            }

            Log4an.e(Tag, "断章所需时间: " + (System.currentTimeMillis() - start));
            br.close();
            isr.close();
            fis.close();
            List<BookContentInfo> finalList = new ArrayList<BookContentInfo>();
            if (temp.size() != 0 && temp.size() * 2 > temp1.size()
                    && temp.size() * 2 > temp2.size()) {
                finalList.addAll(temp);
            } else if (temp1.size() >= temp2.size()) {
                finalList.addAll(temp1);
            } else {
                finalList.addAll(temp2);
            }
            Log4an.e(Tag, "finalList is null=" + (finalList == null ? true : false) + ",size="
                    + finalList.size() + ",filepath is equal=" + filePath.equals(this.filePath));
            if (finalList.size() > 0 && filePath.equals(this.filePath)) {
                TxtCatalogDao.getInstance().saveTxtCatalogList(finalList, filePath, (int) fileSize);
                Log4an.e(Tag, "startCheck: 6.保存 目录：size:" + finalList.size() + ",path:" + filePath);
            }
            // 智能断章正常结束，路径保存到sp中
            if (filePath.equals(this.filePath)) {
                Log4an.i("TxtTool", "filePath=" + filePath + "\n自动断章完成，数据保存=" + true + ",isRunOld="
                        + TxtCatalogDao.getInstance().isRunOld);
                SharedPreferenceUtil.setFileCatalogTool(context, filePath, true,
                        TxtCatalogDao.getInstance().isRunOld);
            }
            if (checkingListener != null && filePath.equals(this.filePath)) {
                checkingListener.onFinish(finalList, true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            isChecking = false;
            this.filePath = null;
        }
    }

    // public static List<BookContentInfo> list = new ArrayList<BookContentInfo>();
}
